联调测试:插件下载 & 动态加载模块
概述
本节将之前开发的插件下载和解压逻辑整合到 Electron 应用中,完成渲染进程与主进程的 IPC 通信联调,实现从点击插件列表到动态加载模块的完整流程。
IPC 通信架构
渲染进程 (Renderer) 主进程 (Main)
┌─────────────────┐ ┌─────────────────┐
│ 用户点击插件列表 │ │ │
│ │ │ │ │
│ ▼ │ IPC send │ │
│ ipcRenderer.send├─────────────────>│ ipcMain.on │
│ ('download-ext',│ download-ext │ │
│ item) │ │ 1. 下载 ZIP │
│ │ │ 2. 解压到本地 │
│ │ │ 3. 动态加载模块 │
│ │<─────────────────┤ 4. 执行插件 │
│ 更新 UI 状态 │ 回调/返回结果 │ │
└─────────────────┘ └─────────────────┘
text
渲染进程实现
// renderer/preload.ts
import { ipcRenderer } from 'electron'
// 新增下载插件方法
export function downloadExt(item: ExtensionItem) {
ipcRenderer.send('download-ext', item)
}
typescript
主进程实现
依赖安装
npm install node-fetch fs-extra adm-zip
bash
核心代码
// main/index.ts
import { ipcMain } from 'electron'
import fetch from 'node-fetch'
import fs from 'fs-extra'
import path from 'path'
import os from 'os'
const HOME_DIR = os.homedir()
const EXTENSIONS_DIR = path.join(HOME_DIR, '.electron-tools/extensions')
// 下载远端 ZIP
async function downloadRemoteZip(url: string): Promise<Buffer> {
const response = await fetch(url)
return Buffer.from(await response.arrayBuffer())
}
// 解压 ZIP
async function unzip(zipBuffer: Buffer, targetPath: string): Promise<string> {
const AdmZip = require('adm-zip')
const zip = new AdmZip(zipBuffer)
zip.extractAllTo(targetPath, true)
return targetPath
}
// 监听下载事件
ipcMain.on('download-ext', async (event, item) => {
try {
// 1. 下载 ZIP
const zipBuffer = await downloadRemoteZip(item.url)
// 2. 确保目录存在
await fs.ensureDir(EXTENSIONS_DIR)
// 3. 解压
const pluginDir = path.join(EXTENSIONS_DIR, item.name)
await unzip(zipBuffer, pluginDir)
// 4. 动态加载并执行
const plugin = require(path.join(pluginDir, 'index.js'))
if (typeof plugin.run === 'function') {
plugin.run()
}
event.reply('download-ext-complete', { success: true, name: item.name })
} catch (error) {
event.reply('download-ext-error', { success: false, error: String(error) })
}
})
typescript
常见导入错误修复
// 错误: 缺少 path 模块
import path from 'path' // 修正: const path = require('path')
// 错误: fs-extra 未安装
npm install fs-extra // 修正: 安装依赖
// ESLint 错误: 未使用的变量
// 删除未使用的变量声明
typescript
动态加载模块
// 使用 require 加载 CommonJS 模块
const plugin = require(pluginPath)
// 使用 import 加载 ES Module
const plugin = await import(pluginPath)
// 执行插件入口函数
if (typeof plugin.run === 'function') {
plugin.run()
}
typescript
关键要点
- 渲染进程通过
ipcRenderer.send('download-ext', item)发送下载请求 - 主进程接收
item参数,执行下载、解压、动态加载完整流程 - 依赖安装:
node-fetch(HTTP 请求)、fs-extra(文件操作)、adm-zip(解压) - 插件目录统一存放在
~/.electron-tools/extensions/ - 后续可扩展为 CLI 入口或插件管理界面
↑